`include "PRV564Config.v"
`include "PRV564Define.v"

// Author: Dingbang Liu
// Description: Multiplication & Division Pipeline (abbreviated MD Pipeline)

module md_wrapper(
// Global signals
    input wire clk,
    input wire arst,
    input wire flush,
// Input handshake
    input wire i_valid,
    input wire[7:0] i_opcode,
    input wire[1:0] i_opinfo,
    input wire[63:0] i_data1,
    input wire[63:0] i_data2,
    input wire[7:0] i_tag,
    input wire[1:0] i_priv,
    input wire[`XLEN-1:0] i_pc,
    output wire i_ready,
// Output handshake
    output wire[63:0] d_result,
    output wire d_valid,
    output wire[7:0] d_tag,
    output wire[1:0] d_priv,
    output wire[`XLEN-1:0] d_pc,
    input wire d_ready
    );

    wire stallreq_from_execute;
    wire stallreq_from_output;
    wire flush_for_decode;
    wire stall;
    wire flush_for_execute;
    // Execute input
    wire[127:0] ex_data1;
    wire[127:0] ex_data2;
    wire ex_div;
    wire[7:0] ex_opcode;
    wire[1:0] ex_opinfo;
    //divide
    wire [63:0]diver,divee,div,mod;
    wire div_start,div_finish;
    // Execute output
    wire ex_valid;
    wire[63:0] ex_result;
    wire[7:0] ex_tag;
    wire[1:0] ex_priv;
    wire[`XLEN-1:0] ex_pc;
    wire div_idle;

    assign stallreq_from_output = ~arst & ~d_ready & d_valid;
    assign flush_for_decode = stallreq_from_execute | flush;
    assign flush_for_execute = flush;
    assign stall = stallreq_from_output;
    assign i_ready = ~arst & ~flush & ~stallreq_from_execute & ~stallreq_from_output & i_valid;
    md_decode               u_decode(
            .clk            (clk),
            .arst           (arst),
            .stall          (stall),
            .flush          (flush_for_decode),
            .handshake      (i_ready & i_valid),
            .i_opcode       (i_opcode),
            .i_opinfo       (i_opinfo),
            .i_data1        (i_data1),
            .i_data2        (i_data2),
            .i_tag          (i_tag),
            .i_priv         (i_priv),
            .i_pc           (i_pc),
            .ex_data1       (ex_data1),
            .ex_data2       (ex_data2),
            .ex_div         (ex_div),
            .ex_opcode      (ex_opcode),
            .ex_opinfo      (ex_opinfo),
            .ex_tag         (ex_tag),
            .ex_priv        (ex_priv),
            .ex_pc          (ex_pc)
             );
    md_execute              u_execute(
            .clk            (clk),
            .arst           (arst),
            .stall          (stall),
            .flush          (flush_for_execute),
            .ex_data1       (ex_data1),
            .ex_data2       (ex_data2),
            .ex_div         (ex_div),
            .ex_opcode      (ex_opcode),
            .ex_opinfo      (ex_opinfo),
            .ex_tag         (ex_tag),
            .ex_priv        (ex_priv),
            .ex_pc          (ex_pc),
            .d_result       (d_result),
            .d_valid        (d_valid),
            .d_tag          (d_tag),
            .d_priv         (d_priv),
            .d_pc           (d_pc),
            .stallreq       (stallreq_from_execute),

            .q              (div), // quotient
            .r              (mod), // remainder
            .div_valid      (div_finish),
            .div_idle       (div_idle),
            .dividend       (divee),
            .divisor        (diver),
            .div_start      (div_start)
    ); 
    MulCyc_Div#(
		.DIV_WIDTH(64),
		.UNROLL_COEFF(0)
	)DIVIDER
	(
	.clk                    (clk),
	.rst                    (arst),
	.flush                  (flush_for_execute),
	.stall                  (stall),
	.start                  (div_start),
	
	.DIVIDEND               (divee),//被除数
	.DIVISOR                (diver),//除数
	
	.DIV                    (div),//商
	.MOD                    (mod),//余数
	.div_idle               (div_idle),
	.calc_done              (div_finish) //Calculate done
	);

endmodule

